package org.zoomdev.zoom.dao.adapters.result;

import org.zoomdev.zoom.common.exceptions.ZoomException;
import org.zoomdev.zoom.common.utils.Classes;
import org.zoomdev.zoom.dao.ResultSetParser;
import org.zoomdev.zoom.dao.adapters.ResultSetAdapter;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.sql.Clob;
import java.util.*;

public class ResultSetAdapters {


    private static final Map<String, ResultSetAdapter> pool = new HashMap<>();

    public static ResultSetParser getListParser(ResultSetParser parser) {
        return rs -> {
            List list = new ArrayList();
            while (rs.next()) {
                list.add(parser.fromResultSet(rs));
            }
            return list;
        };
    }

    public static ResultSetParser getOneParser(ResultSetParser parser) {
        return rs -> {
            if (rs.next()) {
                return parser.fromResultSet(rs);
            }
            return null;
        };
    }

    /**
     * 获取的数据直接往field方向靠拢
     *
     * @param columnType
     * @param type
     * @return
     */
    public static ResultSetAdapter create(Class<?> columnType, Type type) {
        if (type == String.class) {
            return StringResultSetAdapter.ADAPTER;
        }

        if (type == Integer.class || type == int.class) {
            return IntegerResultSetAdapter.ADAPTER;
        }

        if (type == Long.class || type == long.class) {
            return LongResultSetAdapter.ADAPTER;
        }

        if (type == BigDecimal.class) {
            return BigDecimalResultSetAdapter.ADAPTER;
        }

        if (type == Short.class || type == short.class) {
            return ShortResultSetAdapter.ADAPTER;
        }

        if (type == Byte.class || type == byte.class) {
            return ByteResultSetAdapter.ADAPTER;
        }

        if (type == Boolean.class || type == boolean.class) {
            return BooleanResultSetAdapter.ADAPTER;
        }

        if (type == Double.class || type == double.class) {
            return DoubleResultSetAdapter.ADAPTER;
        }

        if (type == Float.class || type == float.class) {
            return FloatResultSetAdapter.ADAPTER;
        }

        if (type == java.sql.Date.class) {
            return DateResultSetAdapter.ADAPTER;
        }

        if (type == java.sql.Timestamp.class) {
            return TimestampResultSetAdapter.ADAPTER;
        }


        String key = getKey(type, columnType);
        ResultSetAdapter adapter = pool.get(key);
        if (adapter == null) {
            adapter = create2(columnType, type);
            pool.putIfAbsent(key, adapter);
        }
        return adapter;

    }

    static String getKey(Type fieldType, Class<?> columnType) {
        return fieldType.getTypeName() + "2" + columnType.getName();
    }

    protected static ResultSetAdapter create2(Class<?> columnType, Type type) {

        //enum
        if (type instanceof Class) {
            Class<?> clazz = (Class<?>) type;
            if (Classes.isEnum(clazz)) {
                if (columnType == String.class) {
                    return new StringEnumResultSetAdapter(clazz);
                }
            }
        }


        if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;
            if (pt.getRawType() instanceof TypeVariable) {
                throw new ZoomException("不支持的类型:" + type);
            }
            Class<?> rawType = (Class<?>) pt.getRawType();
            if (Map.class.isAssignableFrom(rawType) || Iterator.class.isAssignableFrom(rawType)) {
                if (columnType == Clob.class) {
                    return new ClobJsonResultSetAdapter(type);
                }
                //需要做中转
                return new StringJsonResultSetAdapter(type);
            }
        }

        return new WrapTypeResultSetAdapter(columnType, type);
        //  throw new ZoomException("不支持的字段类型" + type);

    }
}
